#region Debug Preprocessor
#if !DEBUG || !TRACE
    // If not debug then take out all debugging.
    #define CPU_DEBUG_OFF
    #undef CPU_DEBUG_ALL
#endif

// Check if both are defined and raise error.
#if CPU_DEBUG_ALL && CPU_DEBUG_OFF
    #error CPU_DEBUG_ALL and CPU_DEBUG_OFF cannot both be defined
#endif

// Define cpu debug if any of the subsections debuging are turned on.
#if (CPU_MEM_DEBUG || CPU_INT_DEBUG || CPU_STACK_DEBUG || CPU_INS_DEBUG || CPU_TIMING_DEBUG) && !CPU_DEBUG_ALL && !CPU_DEBUG_OFF
    #define CPU_DEBUG
#endif

// Turn on all cpu debug.
#if CPU_DEBUG_ALL
    #define CPU_DEBUG
    #define CPU_MEM_DEBUG
    #define CPU_INT_DEBUG
    #define CPU_INS_DEBUG
    #define CPU_STACK_DEBUG
    #define CPU_TIMING_DEBUG
#endif

// Turn of all cpu debug.
#if CPU_DEBUG_OFF
    #undef CPU_DEBUG
    #undef CPU_MEM_DEBUG
    #undef CPU_INT_DEBUG
    #undef CPU_INS_DEBUG
    #undef CPU_STACK_DEBUG
    #undef CPU_TIMING_DEBUG
#endif


#endregion Debug Preprocessor
using System;
using System.Collections.Generic;
using System.Text;

namespace Zsa.Emulation.Processor
{
    /// <summary>
    /// Cpu Memory methods.
    /// </summary>
    public partial class Cpu6502
    {
        #region Fields
        /// <summary>
        /// The offset for the stack.  
        /// </summary>
        private const int _StackOffset = 0x100;
        /// <summary>
        /// Reference to main nes memory in cpu map.
        /// </summary>
        private byte[] _MainMemory;
        #endregion Fields


        #region Methods

        #region Stack Methods
        /// <summary>
        /// Pushes a value on to the stack.
        /// </summary>
        /// <param name="value">The value.</param>
        private void Push(byte value)
        {
            _RegisterStackPointer -= 1;
            _MainMemory[((byte)_RegisterStackPointer + 1) + _StackOffset] = value;
            #if DEBUG
            LogPush(value);
            #endif
        }

        /// <summary>
        /// Pushes a value an address on the stack.
        /// </summary>
        /// <param name="value">The value.</param>
        private void PushAddress(ushort value)
        {
            _RegisterStackPointer -= 2;
            _MainMemory[((byte)_RegisterStackPointer + 1) + _StackOffset] = (byte)(0xFF&value);
            _MainMemory[((byte)_RegisterStackPointer + 2) + _StackOffset] = (byte)((0xFF00 & value)>>8);
            #if DEBUG
            LogPush(value);
            #endif
        }

        /// <summary>
        /// Pops a value off stack.
        /// </summary>
        /// <returns></returns>
        private byte Pop()
        {
            _RegisterStackPointer++;
            #if DEBUG
            LogPop(_MainMemory[((byte)_RegisterStackPointer) + _StackOffset]);
            #endif
            return _MainMemory[((byte)_RegisterStackPointer) + _StackOffset];
        }

        /// <summary>
        /// Pops a address off the stack, and sets the program counter.
        /// </summary>
        /// <returns></returns>
        private void PopAddress()
        {
            // Move backwards two
            _RegisterStackPointer += 2;
            #if DEBUG
            LogPop((ushort)(_MainMemory[((byte)_RegisterStackPointer - 1) + _StackOffset] |
                    (_MainMemory[_RegisterStackPointer + _StackOffset] << 8)));
            #endif
            _RegisterProgramCounter = ((ushort)(_MainMemory[((byte)_RegisterStackPointer - 1) + _StackOffset] |
                    (_MainMemory[_RegisterStackPointer + _StackOffset] << 8)));
        }
        #endregion Stack Methods

        /// <summary>
        /// Reads the indirect X address from zero page.
        /// </summary>
        /// <returns></returns>
        private void ReadAddressIndirectX()
        {
            // Get the address in the zero page.
            _MemoryAddress = (ushort)((byte)(_BufferTemp[1] + _RegisterX));

            // Read the byte from memory.
            _MemoryAddress = (ushort)(_MainMemory[_MemoryAddress] |
                ((_MemoryAddress == 0xFF ? _MainMemory[0] : _MainMemory[_MemoryAddress + 1]) << 8));

        }

        /// <summary>
        /// Reads the indirect Y address from zero page.
        /// </summary>
        /// <returns></returns>
        private void ReadAddressIndirectY()
        {
            // Get the address in the zero page.
            _MemoryAddress = (ushort)(_BufferTemp[1]);
            // Read the address from memory.
            _MemoryAddress = (ushort)((_Memory.Read(_MemoryAddress) |
                (_Memory.Read(_MemoryAddress == 0xFF ? 0 : _MemoryAddress + 1) << 8)) + _RegisterY);


        }
        #endregion Methods
    }
}
